﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace MapsEditor
{
    public partial class Form1 : Form
    {
        LevelState state;
        Point mouseDownPosition;

        public Form1()
        {
            InitializeComponent();
            state = new LevelState();
            state.Level = new SubLevel() { Position = new Point(50, 50), Size = new Point(300, 300) };
            state.OnSolidChanged += new EventHandler(SetButtonsStates);
            lbSolids.DisplayMember = "Id";
            lbSolids.Items.Add(state.Level);
            MouseWheel += new MouseEventHandler(Form1_MouseWheel);
        }
        // прозрачность формы
        private void trackBarTransparency_Scroll(object sender, EventArgs e)
        {
            this.Opacity = 1 - trackBarTransparency.Value / 100.0;
        }
        // прозрачность панели рисования
        private void chbAllowTransparency_CheckedChanged(object sender, EventArgs e)
        {
            TransparencyKey = chbAllowTransparency.Checked ? Color.Cyan : Color.Empty;
        }
        // изменяет состояния кнопок
        private void SetButtonsStates(object sender, EventArgs e)
        {
            bool value = state.Solid != null;
            btnCreateSolid.Enabled = !value;
            btnSaveSolid.Enabled = value;
            btnDeleteSolid.Enabled = value;
        }
        // создание тела
        private void btnCreateSolid_Click(object sender, EventArgs e)
        {
            state.CreateSolid();
            lbSolids.Items.Add(state.Solid);
            lbSolids.SelectedItem = state.Solid;
        }
        // сохраняем тело - добавляем его в список тел карты
        private void btnSaveSolid_Click(object sender, EventArgs e)
        {
            state.SaveSolid();
            lbSolids.SelectedItem = state.Level;
            panel1.Invalidate();
        }
        // удаляем объект из списка объетов карты
        private void btnDeleteSolid_Click(object sender, EventArgs e)
        {
            SubSolid solid = state.Solid;
            state.DeleteSolid();
            lbSolids.Items.Remove(solid);
            panel1.Invalidate();
        }
        // рисование
        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.FillRectangle(Brushes.Cyan, state.Level.Position.X, state.Level.Position.Y, state.Level.Size.X, state.Level.Size.Y);
            foreach (var solid in state.Level.Solids)
            {
                g.FillPolygon(Brushes.Red, solid.Vertices);
            }
            if (state.Solid != null)
            {
                g.FillPolygon(Brushes.Orange, state.Solid.Vertices);
            }
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            mouseDownPosition = e.Location;
        }
        // создаём прямоугольник или перемещаем существующий
        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            if (mouseDownPosition == e.Location)
            {
                return;
            }
            if (state.Solid == null)
            {
                Point delta = new Point(e.Location.X - mouseDownPosition.X, e.Location.Y - mouseDownPosition.Y);
                state.MoveLevel(delta);
            }
            else if (state.Solid.State == SubSolidState.Creating)
            {
                state.CreateSolid(mouseDownPosition, e.Location);
            }
            else
            {
                Point delta = new Point(e.Location.X - mouseDownPosition.X, e.Location.Y - mouseDownPosition.Y);
                state.MoveSolid(delta);
            }
            UpdateInfo();
            panel1.Invalidate();
        }
        // поворот тела
        void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (state.Solid != null)
            {
                double delta = e.Delta * 0.001;
                state.RotateSolid((float)delta);
                tbAngle.Text = (state.Solid.Angle / Math.PI * 180).ToString("0.000");
                panel1.Invalidate();
            }
        }

        private void lbSolids_SelectedIndexChanged(object sender, EventArgs e)
        {
            // null, если выделена карта
            state.Solid = lbSolids.SelectedItem as SubSolid;
            UpdateInfo();
            panel1.Invalidate();
        }
        // обновляем информацию о выделенном объекте
        private void UpdateInfo()
        {
            if (state.Solid == null)
            {
                tbPosX.Text = state.Level.Position.X.ToString();
                tbPosY.Text = state.Level.Position.Y.ToString();
                tbWidth.Text = state.Level.Size.X.ToString();
                tbHeight.Text = state.Level.Size.Y.ToString();
                tbAngle.Text = "0";
            }
            else
            {
                tbPosX.Text = state.Solid.Position.X.ToString();
                tbPosY.Text = state.Solid.Position.Y.ToString();
                tbWidth.Text = state.Solid.Size.X.ToString();
                tbHeight.Text = state.Solid.Size.Y.ToString();
                tbAngle.Text = (state.Solid.Angle / Math.PI * 180).ToString("0.000");
            }
        }
        // применяем введенные данные
        private void btnAccept_Click(object sender, EventArgs e)
        {
            bool isOk = true;
            bool isAllOk = true;
            int x;
            int y;
            tbPosX.ForeColor = (isOk = int.TryParse(tbPosX.Text, out x)) ? Color.Black : Color.Red;
            isAllOk &= isOk;
            tbPosY.ForeColor = (isOk = int.TryParse(tbPosY.Text, out y)) ? Color.Black : Color.Red;
            isAllOk &= isOk;
            Point position = new Point(x, y);
            tbWidth.ForeColor = (isOk = int.TryParse(tbWidth.Text, out x)) ? Color.Black : Color.Red;
            isAllOk &= isOk;
            tbHeight.ForeColor = (isOk = int.TryParse(tbHeight.Text, out y)) ? Color.Black : Color.Red;
            isAllOk &= isOk;
            Point size = new Point(x, y);
            float angle;
            tbAngle.ForeColor = (isOk = float.TryParse(tbAngle.Text, out angle)) ? Color.Black : Color.Red;
            isAllOk &= isOk;
            if (!isAllOk)
            {
                return;
            }
            if (state.Solid == null)
            {
                // редактируем уровень
                state.Level.Position = position;
                state.Level.Size = size;
            }
            else
            {
                state.Solid.Position = position;
                state.Solid.Size = size;
                state.Solid.Angle = (float)(angle / 180.0 * Math.PI);
                state.Solid.CalcVertices();
            }
            panel1.Invalidate();
        }
        // открываем файл
        private void tsmiOpen_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                lbSolids.Items.Clear();
                lbSolids.Items.Add(state.Level);
                SubSolid.ResetId();
                state.Open(openFileDialog1.OpenFile());
                foreach (var solid in state.Level.Solids)
                {
                    lbSolids.Items.Add(solid);
                }
                lbSolids.SelectedItem = state.Level;
            }
            panel1.Invalidate();
        }
        // сохраняем карту в файл
        private void tsmiSave_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(saveFileDialog1.FileName) ||
                (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK))
            {
                state.Save(saveFileDialog1.OpenFile());
            }
        }
        // сохраняем карту в файл
        private void tsmiSaveAs_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
            state.Save(saveFileDialog1.OpenFile());
        }
        // изменяем масштаб карты и объектов
        private void btnScale_Click(object sender, EventArgs e)
        {
            double koef;
            if (double.TryParse(tbScale.Text, out koef))
            {
                state.ScaleAll(koef);
                panel1.Invalidate();
            }
        }
    }
}
